package cn.net.isir.core;

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author liuxubo
 * @filename JedisManager.java
 * @package cn.net.isir.core
 * @email lxb@isetech.cn
 * @date 2018/11/08
 * @comment
 * @since 1.8
 */
public class JedisManager {
    /**
     * 日志
     */
    private static Logger logger = Logger.getLogger(JedisManager.class);

    /**
     * 缓存资源池
     */
    private JedisPool jedisPool;

    /**
     * 数据库索引(默认0)
     */
    private Integer dbIndex;

    public Integer getDbIndex() {
        return dbIndex;
    }

    public void setDbIndex(Integer dbIndex) {
        this.dbIndex = dbIndex;
    }

    public void setJedisPool(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    public JedisPool getJedisPool() {
        return jedisPool;
    }

    /**
     * 获取缓存
     *
     * @return jedis对象
     */
    public Jedis getJedis() {
        if (jedisPool == null) {
            logger.error(new RuntimeException("jedisPool is null!Please check the jedis service."));
            //exit
//            System.exit(0);
            return null;
        }
        try {
            Jedis jedis = jedisPool.getResource();
            jedis.select(dbIndex);
            return jedis;
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            throw new RuntimeException(ex);
        }
    }

    /**
     * 检查是否可以成功获取jedis
     *
     * @return true表示可以成功获取，false表示获取失败
     */
    public boolean checkResource() {
        try {
            Jedis jedis = jedisPool.getResource();
            jedis.select(dbIndex);
            returnResource(jedis);
        } catch (Exception ex) {
            logger.error(new RuntimeException("jedisPool is null!Please check the jedis service."));
            return false;
        }
        return true;
    }

    /**
     * 归还jedis资源(申请并使用之后，必须归还)
     *
     * @param jedis 要归还的jedis对象
     */
    private void returnResource(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

    /**
     * 从缓存中获取数据
     *
     * @param key key
     * @return value
     */
    public String get(String key) {
        Jedis jedis = null;
        String result;
        try {
            jedis = getJedis();
            result = jedis.get(key);
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 查找存在的key
     *
     * @param key key
     * @return key集合
     */
    public Set<String> getKeys(String key) {
        Jedis jedis = null;
        Set<String> result;
        try {
            jedis = getJedis();
            result = jedis.keys(key);
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 查找存在的数据
     *
     * @param key key
     * @return Map
     */
    public Map<String, Object> getEntityMap(String key) {
        Jedis jedis = null;
        Map<String, Object> map;
        try {
            jedis = getJedis();
            Set<String> keys = jedis.keys(key);
            map = new HashMap<>();
            Jedis finalJedis = jedis;
            keys.forEach(item -> map.put(item, finalJedis.get(item)));
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        } finally {
            returnResource(jedis);
        }
        return map;
    }

    /**
     * 新增/修改数据
     *
     * @param key   key
     * @param value value
     */
    public void set(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.set(key, value);
        } catch (Exception ex) {
            logger.error(ex);
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 设置过期时间
     *
     * @param key     key
     * @param seconds 过期时间(秒)
     */
    public void expire(String key, int seconds) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.expire(key, seconds);
        } catch (Exception ex) {
            logger.error(ex);
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 删除数据
     *
     * @param key key
     */
    public void delete(String key) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.del(key);
        } catch (Exception ex) {
            logger.error(ex);
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 使用字节形式的数据获取
     *
     * @param key key
     * @return value
     */
    public byte[] get(byte[] key) {
        Jedis jedis = null;
        byte[] result;
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            result = jedis.get(key);
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        } finally {
            returnResource(jedis);
        }
        return result;
    }

    /**
     * 使用字节形式的数据存放
     *
     * @param key   key
     * @param value value
     */
    public void set(byte[] key, byte[] value) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            jedis.set(key, value);
        } catch (Exception ex) {
            logger.error(ex);
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 字节形式的设置过期时间
     *
     * @param key     key
     * @param seconds 过期时间(秒)
     */
    public void expire(byte[] key, int seconds) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            jedis.expire(key, seconds);
        } catch (Exception ex) {
            logger.error(ex);
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * 字节形式的删除数据
     *
     * @param key key
     */
    public void delete(byte[] key) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.select(dbIndex);
            jedis.del(key);
        } catch (Exception ex) {
            logger.error(ex);
        } finally {
            returnResource(jedis);
        }
    }
}
